﻿using System;
using System.Windows;
using Tiny.Imaging.Filter.PixelLibrary;

namespace Tiny.Imaging.Filter.PointFilter
{
    [Flags]
    public enum RgbChannel
    {
        R = 0x1,
        G = 0x2,
        B = 0x4,
        Rgb = R | G | B,
    }

    public class CurvesFilter : BaseFilter.BaseFilter
    {
        // Bezier Curve
        protected double[] Bezier;

        public CurvesFilter(Func<int, int, int> blend = null, int opacity = 100)
            : base(blend, opacity)
        {
        }

        public CurvesFilter(RgbChannel channel, Point start, Point ctrl1, Point ctrl2, Point end)
        {
            Channel = channel;
            Bezier = PrepopulateBezier(start, ctrl1, ctrl2, end);
        }

        public RgbChannel Channel { get; set; }

        public override int Process(Rgba rgba)
        {
            if ((Channel & RgbChannel.R) == RgbChannel.R)
            {
                rgba.R = Blend(rgba.R, (int)Bezier[rgba.R]);
            }

            if ((Channel & RgbChannel.G) == RgbChannel.G)
            {
                rgba.G = Blend(rgba.G, (int)Bezier[rgba.G]);
            }

            if ((Channel & RgbChannel.B) == RgbChannel.B)
            {
                rgba.B = Blend(rgba.B, (int)Bezier[rgba.B]);
            }

            return rgba.ToInteger();
        }

        public static double[] PrepopulateBezier(Point start, Point ctrl1, Point ctrl2, Point end)
        {
            double[] bezier = PixelUtil.BezierMapping(start, ctrl1, ctrl2, end);

            if (start.X > 0)
            {
                for (int i = 0; i < (int)start.X; ++i)
                {
                    bezier[i] = (int)start.Y;
                }
            }

            if (end.X < 255)
            {
                for (var i = (int)end.X; i < 256; ++i)
                {
                    bezier[i] = (int)end.Y;
                }
            }

            return bezier;
        }
    }
}